package com.zwh.se.oop.comprehensive;

/**
 * 什么时候使用super:
 * 1、在子类方法中，调用父类被覆盖的方法，此时必须使用super
 * 2、在子类构造器中，调用父类构造器，此时必须使用super语句
 *
 * super 关键字表示是 直接父类 对象的引用，子类要访问父类成员时可以使用super。
 * super只是一个关键字，内部没有引用（地址）。
 *
 * [1]super 调用构造方法必须写在子类构造方法的第一句。
 * [2]如果子类构造方法没有显式调用父类构造方法时，那么jvm会默认调用父类的无参构造super()
 *
 * @author yexi
 */
public class ClassToTestSuper extends ClassToTestThis {

    private Long id;
    private String name = "儿子";

    public ClassToTestSuper() {
        //子类构造方法可以通过super调用父类构造器
        super();
    }

    public ClassToTestSuper(String name, int age, Long id) {
        //super();如果子类构造方法没有显式调用父类构造方法,那么jvm也会默认帮你调用父类的无参构造
        this.id = id;
        super.setName(name);
    }

    public ClassToTestSuper(String name, Long id) {
        super(name,45);//如果super显式地指明了父类构造器,则jvm就不会再帮你调用父类无参构造
        this.id = id;
        //如果父类的字段没有被private所修饰的话,那么super也可以直接调用父类的字段来使用
        this.name = super.state;
        //当然,没有被private修饰其实本身也不需要通过super来使用亦可。super主要还是用于子类与父类的方法或者属性重名的时候。
        this.name = state;
    }

    public ClassToTestSuper(String name) {
        //在构造器中，super调用父类构造器和this调用子类构造器只能存在一个，两者不能共存
        //因为super修饰构造器要放在第一行，this修饰构造器也要放在第一行
        this();
        //super();
    }

    @Override
    public void sayName() {
        System.out.println("儿子名字:" + this.name);
    }

    public void say() {
        //当子类和父类的方法重名时，你要想使用父类的方法，必须加上修饰符super.，只能通过super.方法来调用
        super.sayName();//调用父类被覆盖的方法
        sayName();//调用本类中的方法
    }

    @Override
    public String toString() {
        return "ClassToTestSuper{" +
                "id=" + id +
                "} " + super.toString();
    }

    public static void main(String[] args) {
        //由于父类的无参构造被特地设计过,所以更能体现出 super 的作用
        ClassToTestSuper c1 = new ClassToTestSuper();
        System.out.println(c1);
        c1.say();
        ClassToTestSuper c2 = new ClassToTestSuper("小红",0,1L);
        System.out.println(c2);
        c2.say();
        ClassToTestSuper c3 = new ClassToTestSuper("小白", 3L);
        System.out.println(c3);
        c3.say();
    }
}
